using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.ComponentModel;
using System.Text;
using System.Threading;
using System.IO;

namespace NewTcGui
{
	/* at this time only mounting volumes, 
	 * TODO: evaluate which volumes need to be mounted 
	 * TODO: check if user has privigiles to run truecrypt,
	 * if not ask for a password*/
	public class TcMounter
	{
		private string tcPath;
		private StringBuilder output;
		private Process tcProc;

		public TcMounter(string trueCryptPath)
		{
			tcPath = trueCryptPath;
			//output = new StringBuilder();
		}

		//each volume has own password
		public MountHelper Mount(MountPoint mp, string passwd)
		{
			MountHelper mountHlp = new MountHelper(mp);
			output = new StringBuilder();
			
			SetProcessProperties();
			tcProc.StartInfo.Arguments = 
				String.Format("{0} {1} {2}",  mp.dev, mp.dir, mp.parameters);
			
			try
			{
				tcProc.Start();
				tcProc.BeginOutputReadLine();
				tcProc.BeginErrorReadLine();
							
				//give truecrypt a chance to output error message
				System.Threading.Thread.Sleep(500);
				
				if (output.ToString() == String.Empty) 
				{
					// truecrypt need to set input stream encoding to ASCII
					// because we cant change tcProc.StandardInput.Encoding
					// we need to pack input steam into another writer
					StreamWriter myStream = new StreamWriter(tcProc.StandardInput.BaseStream, Encoding.ASCII); 
							
					myStream.WriteLine(passwd);
					myStream.Close();

					tcProc.StandardInput.Close();
				}
				else
				{
					mountHlp.msg = output.ToString();
					mountHlp.succeed = false;
					return mountHlp;
				}
							
				tcProc.WaitForExit();
				
				if (output.ToString().Contains("Incorrect password")) 
				{
					mountHlp.msg = output.ToString();
					mountHlp.succeed = false;
					mountHlp.wrongPasswd = true;
					return mountHlp;
				}
				else
				{
					if (output.ToString() != String.Empty) 
					{
						mountHlp.msg = output.ToString();
						mountHlp.succeed = false;
						mountHlp.wrongPasswd = false;
						return mountHlp;
					}
				}
				
				System.Console.WriteLine(output.ToString());	
			}
			catch(InvalidOperationException e)
			{
				System.Console.WriteLine("Total error occured ;)");
				mountHlp.msg = e.Message;
				
				return mountHlp;
			}
			catch(Win32Exception e)
			{
				System.Console.WriteLine("Total error occured ;)");
				mountHlp.msg = e.Message;
				
				return mountHlp;
			}
			
			mountHlp.succeed = true;
			return mountHlp;
			
		}
		
	
		private void SetProcessProperties()
		{
			tcProc = new Process();
			tcProc.StartInfo.RedirectStandardError = true;
			tcProc.StartInfo.RedirectStandardOutput = true;
			tcProc.StartInfo.RedirectStandardInput = true;
			tcProc.StartInfo.UseShellExecute = false;
			tcProc.StartInfo.FileName = tcPath;
			tcProc.OutputDataReceived += new DataReceivedEventHandler(ProcessOutput);
			tcProc.ErrorDataReceived += new DataReceivedEventHandler(ProcessError);
		}
		
		private void ProcessOutput(object sendingProcess, DataReceivedEventArgs outLine)
		{
			output.Append(outLine.Data);
			output.Append(Environment.NewLine);
			System.Console.WriteLine(outLine.Data);

		}
		
		private void ProcessError(object sendingProcess, DataReceivedEventArgs outLine)
		{
			output.Append(outLine.Data);
			output.Append(Environment.NewLine);
			System.Console.WriteLine(outLine.Data);
		}
		
		//TODO: need to make it better
		public void UmountAll()
		{
			tcProc = new Process();
			tcProc.StartInfo.FileName = tcPath;
			tcProc.StartInfo.Arguments = "-d";
			tcProc.Start();
			tcProc.WaitForExit();
		}
	}
	
	public class MountHelper
	{
		private MountPoint mp;
		public bool succeed;
		public string msg;
		public bool wrongPasswd;
		
		public MountHelper(MountPoint mp)
		{
			this.mp = mp;
			succeed = false;
			msg = "";
			wrongPasswd = false;
		}
		
		public MountPoint Mp
		{
			get
			{
				return mp;
			}
		}
	}
}
